/*
    This file is part of Raptor.

    Raptor is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Raptor is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Raptor.  If not, see <http://www.gnu.org/licenses/>.

 */

#include "include/configWizard.h"

configWizard::configWizard(QWidget *parent)
        : QWizard(parent)
{
    folderPage =  new configFolderPage();
    setPage(PAGE_FOLDERS, folderPage);

    networkPage = new configNetworkPage();
    setPage(PAGE_NETWORK, networkPage);

    xmlPage = new configXmlPage();
    setPage(PAGE_XML, xmlPage);

    setStartId(PAGE_FOLDERS);
    setOption(HaveHelpButton, false);
    setWizardStyle(ModernStyle);
    setWindowTitle(tr("Configuration Wizard"));
}

configWizard::~configWizard()
{

}

bool configWizard::validateCurrentPage()
{
    if(currentId() == PAGE_FOLDERS)
    {
        raptor = folderPage->raptor();
        downloads = folderPage->downloads();

    } else if(currentId() == PAGE_NETWORK)
    {
        host = networkPage->host();
        port = networkPage->port();
        type = networkPage->type();
        user = networkPage->user();
        pass = networkPage->pass();
        useSSL = networkPage->useSSL();

        xmlPage->setProxy(QNetworkProxy(type, host, port, user, pass));
        xmlPage->setUseSSL(useSSL);

    } else if(currentId() == PAGE_XML)
    {
        hoster = QStringList();
        QPointer<QStandardItemModel> model = xmlPage->hoster();
        for(int i=0; i<model->rowCount(); ++i)
        {
            if(model->item(i, 0)->data(Qt::CheckStateRole) ==  Qt::Checked)
            {
                hoster.append(model->item(i, 1)->text());
            }
        }

        container = QStringList();
        model = xmlPage->container();
        for(int i=0; i<model->rowCount(); ++i)
        {
            if(model->item(i, 0)->data(Qt::CheckStateRole) ==  Qt::Checked)
            {
                container.append(model->item(i, 1)->text());
            }
        }

        //LAST PAGE -> save all to qsettings
        saveToQSettings();
    }

    return true;
}

void configWizard::saveToQSettings()
{
    QSettings settings("raptor-loader", "Raptor");

    settings.setValue("folderRaptor", raptor);
    settings.setValue("folderDownload", downloads);

    settings.setValue("proxy/host", host);
    settings.setValue("proxy/port", port);
    settings.setValue("proxy/type", type);
    settings.setValue("proxy/user", user);
    settings.setValue("proxy/pass", pass);

    settings.setValue("useSSL", useSSL);

    Raptor::S_FOLDERS folders;
    folders.setDirs(raptor, downloads, "captcha", "hoster", "urlContainer");

    for(int i=0; i<hoster.size(); ++i)
    {
        QFile tmpFile(folders.hoster.absolutePath() + QDir::separator() + hoster.at(i) + ".xml");
        if(!tmpFile.exists())
            if(tmpFile.open(QIODevice::WriteOnly))
                tmpFile.close();
    }

    for(int i=0; i<container.size(); ++i)
    {
        QFile tmpFile(folders.container.absolutePath() + QDir::separator() + container.at(i) + ".xml");
        if(!tmpFile.exists())
            if(tmpFile.open(QIODevice::WriteOnly))
                tmpFile.close();
    }
}

configFolderPage::configFolderPage()
{
    raptorLabel = new QLabel(tr("Raptor Folder:"));
    downloadsLabel = new QLabel(tr("Download Folder:"));
    raptorLineEdit = new QLineEdit(QDir::currentPath());
    downloadsLineEdit = new QLineEdit(QDir::currentPath() + QDir::separator() + tr("downloads"));
    raptorPushButton = new QPushButton(tr("Select Folder"));
    downloadsPushButton = new QPushButton(tr("Select Folder"));

    connect(raptorPushButton, SIGNAL(clicked()), this, SLOT(slot_raptorPushButton_clicked()));
    connect(downloadsPushButton, SIGNAL(clicked()), this, SLOT(slot_downloadsPushButton_clicked()));

    mainLayout = new QGridLayout;

    mainLayout->addWidget(raptorLabel, 0, 0);
    mainLayout->addWidget(raptorLineEdit, 0, 1, 1, 2);
    mainLayout->addWidget(raptorPushButton, 0, 3);

    mainLayout->addWidget(downloadsLabel, 1, 0);
    mainLayout->addWidget(downloadsLineEdit, 1, 1, 1, 2);
    mainLayout->addWidget(downloadsPushButton, 1, 3);

    setLayout(mainLayout);
}

configFolderPage::~configFolderPage()
{
    if(raptorLabel) delete raptorLabel;
    if(downloadsLabel) delete downloadsLabel;
    if(raptorLineEdit) delete raptorLineEdit;
    if(downloadsLineEdit) delete downloadsLineEdit;
    if(raptorPushButton) delete raptorPushButton;
    if(downloadsPushButton) delete downloadsPushButton;
}

void configFolderPage::slot_raptorPushButton_clicked()
{
    QString fileName = QFileDialog::getExistingDirectory(this, tr("Open Directory"), raptorLineEdit->text(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
    if(!fileName.isEmpty()) raptorLineEdit->setText(fileName);
}

void configFolderPage::slot_downloadsPushButton_clicked()
{
    QString fileName = QFileDialog::getExistingDirectory(this, tr("Open Directory"), downloadsLineEdit->text(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
    if(!fileName.isEmpty()) downloadsLineEdit->setText(fileName);
}

configNetworkPage::configNetworkPage()
{
    proxy1Label = new QLabel(tr("Proxy settings:"));
    proxy2Label = new QLabel(tr("Authentication required (User, Pass):"));
    proxyHostLineEdit = new QLineEdit("");
    proxyUserLineEdit = new QLineEdit("");
    proxyPassLineEdit = new QLineEdit("");

    proxyPortSpinBox = new QSpinBox();
    proxyPortSpinBox->setRange(0, 65536);

    proxyTypeComboBox = new QComboBox();

    proxyTypeComboBox->addItem("NoProxy", QNetworkProxy::NoProxy);
    proxyTypeComboBox->addItem("HttpProxy", QNetworkProxy::HttpProxy);
    proxyTypeComboBox->addItem("Socks5Proxy", QNetworkProxy::Socks5Proxy);

    sslCheckBox = new QCheckBox(tr("Use SSL"));

    mainLayout = new QGridLayout;

    mainLayout->addWidget(proxy1Label, 0, 0);
    mainLayout->addWidget(proxyHostLineEdit, 0, 1);
    mainLayout->addWidget(proxyPortSpinBox, 0, 2);
    mainLayout->addWidget(proxyTypeComboBox, 0, 3);

    mainLayout->addWidget(proxy2Label, 1, 0, 1, 2, Qt::AlignRight);
    mainLayout->addWidget(proxyUserLineEdit, 1, 2);
    mainLayout->addWidget(proxyPassLineEdit, 1, 3);

    mainLayout->addWidget(sslCheckBox, 2, 0);

    setLayout(mainLayout);
}

configNetworkPage::~configNetworkPage()
{
    if(mainLayout) delete mainLayout;

    if(proxy1Label) delete proxy1Label;
    if(proxy2Label) delete proxy2Label;
    if(proxyHostLineEdit) delete proxyHostLineEdit;
    if(proxyUserLineEdit) delete proxyUserLineEdit;
    if(proxyPassLineEdit) delete proxyPassLineEdit;
    if(proxyPortSpinBox) delete proxyPortSpinBox;
    if(proxyTypeComboBox) delete proxyTypeComboBox;
    if(sslCheckBox) delete sslCheckBox;
}

configXmlPage::configXmlPage(bool const& useSSL)
{
    timeout = 10;

    if(useSSL)
        raptorUrl = QUrl("https://ssl-account.com/raptor-loader.org/raptor.php");
    else
        raptorUrl = QUrl("http://raptor-loader.org/raptor.php");

    connect(&http, SIGNAL(requestFinished(int, bool)), this, SLOT(slot_http_requestFinished(int, bool)));
    connect(&http, SIGNAL(readyRead(const QHttpResponseHeader &)), this, SLOT(slot_http_readyRead(const QHttpResponseHeader &)));
    connect(&http, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(slot_http_sslErrors(const QList<QSslError> &)));

    hosterLabel = new QLabel(tr("Available hoster"));
    hosterLabel->setWordWrap(false);

    containerLabel = new QLabel(tr("Available URL container"));
    containerLabel->setWordWrap(false);

    hosterSandardItemModel = new QStandardItemModel(0, 2);
    hosterSandardItemModel->setHeaderData(0, Qt::Horizontal, tr("Add"));
    hosterSandardItemModel->setHeaderData(1, Qt::Horizontal, tr("Hoster"));

    hosterTreeView = new QTreeView();
    hosterTreeView->setModel(hosterSandardItemModel);
    hosterTreeView->setMinimumSize(600, 100);

    containerSandardItemModel = new QStandardItemModel(0, 2);
    containerSandardItemModel->setHeaderData(0, Qt::Horizontal, tr("Add"));
    containerSandardItemModel->setHeaderData(1, Qt::Horizontal, tr("Container"));

    containerTreeView = new QTreeView();
    containerTreeView->setModel(containerSandardItemModel);
    containerTreeView->setMinimumSize(600, 100);

    mainLayout = new QGridLayout;
    mainLayout->addWidget(hosterLabel, 0, 0);
    mainLayout->addWidget(hosterTreeView, 1, 0);

    mainLayout->addWidget(containerLabel, 2, 0);
    mainLayout->addWidget(containerTreeView, 3, 0);

    setLayout(mainLayout);
}

configXmlPage::~configXmlPage()
{

}

void configXmlPage::setUseSSL(bool const& use)
{
    if(use)
        raptorUrl = QUrl("https://ssl-account.com/raptor-loader.org/raptor.php");
    else
        raptorUrl = QUrl("http://raptor-loader.org/raptor.php");
}

int configXmlPage::setProxy(QNetworkProxy proxy)
{
    return http.setProxy(proxy);
}

void configXmlPage::initializePage()
{
    QStringList listHoster;
    QStringList listContainer;

    try
    {
        listHoster = getXmlName(TYPE_HOSTER);
        listContainer = getXmlName(TYPE_CONTAINER);
    } catch(configXmlPage::E_FILESTATE e)
    {
        if(e == STATE_TIMEOUT)
        {
            QMessageBox msgBox;
            msgBox.setText(tr("Timeout"));
            msgBox.setInformativeText(tr("Connection to raptor-loader.org timed out. Please check your proxy settings."));
            msgBox.setStandardButtons(QMessageBox::Ok);
            msgBox.setDefaultButton(QMessageBox::Ok);
        } else
        {
            qDebug() << "configXmlPage: Error: " << e;
        }
    }

    hosterSandardItemModel->removeRows(0, hosterSandardItemModel->rowCount());
    for(int i=0; i<listHoster.size(); ++i)
    {
        QList<QStandardItem *> listItem;

        //checked
        QStandardItem *item = new QStandardItem("");
        item->setCheckable(true);
        item->setEditable(false);
        item->setCheckState(Qt::Checked);
        listItem.append(item);

        //link
        QString tmpName = listHoster.at(i);
        tmpName.replace(".xml", "");

        QStandardItem *itemName = new QStandardItem(tmpName);
        itemName->setEditable(false);
        listItem.append(itemName);

        hosterSandardItemModel->appendRow(listItem);
    }

    containerSandardItemModel->removeRows(0, containerSandardItemModel->rowCount());
    for(int i=0; i<listContainer.size(); ++i)
    {
        QList<QStandardItem *> listItem;

        //checked
        QStandardItem *item = new QStandardItem("");
        item->setCheckable(true);
        item->setEditable(false);
        item->setCheckState(Qt::Checked);
        listItem.append(item);

        //link
        QString tmpName = listContainer.at(i);
        tmpName.replace(".xml", "");

        QStandardItem *itemName = new QStandardItem(tmpName);
        itemName->setEditable(false);
        listItem.append(itemName);

        containerSandardItemModel->appendRow(listItem);
    }
}

QByteArray configXmlPage::getPostArray(QString const& action)
{
    QByteArray post = "";

    post.append("action=" + QUrl::toPercentEncoding(action));
    post.append("&version=" + QUrl::toPercentEncoding(QCoreApplication::applicationVersion()));

    return post;
}

QStringList configXmlPage::getXmlName(E_TYPE const& type)
{
    QStringList tmpList;

    response.clear();

    QHttpRequestHeader header("POST", raptorUrl.path());
    header.setValue("Host", raptorUrl.host());
    header.setValue("Content-Type", "application/x-www-form-urlencoded");

    if(raptorUrl.toString().left(5) == "https")
    {
            http.setHost(raptorUrl.host(), QHttp::ConnectionModeHttps);
    } else
    {
            http.setHost(raptorUrl.host());
    }

    QByteArray post = getPostArray("listFiles");

    if(type == TYPE_HOSTER)
      post.append("&type=" + QUrl::toPercentEncoding("hoster"));
    else
      post.append("&type=" + QUrl::toPercentEncoding("container"));

    state = STATE_WAITING;

    QDateTime now = QDateTime::currentDateTime();

    waitingId = http.request(header, post);

    while(state == STATE_WAITING)
    {
        qApp->processEvents(QEventLoop::WaitForMoreEvents | QEventLoop::ExcludeUserInputEvents);

        if(now.secsTo(QDateTime::currentDateTime()) >= timeout)
        {
            waitingId = -1;
            http.abort();
            state = STATE_TIMEOUT;

            throw STATE_TIMEOUT;
        }
    }

    tmpList = QString(response).split("[[:ROW:]]");

    return tmpList;
}

void configXmlPage::slot_http_requestFinished(int requestId, bool httpError)
{
    //nur reagieren, wenn auch beabsichtigt
    if(waitingId != requestId) return;

    if(httpError)
    {
      response = http.errorString().toAscii();
      state = STATE_ERROR;
    } else
    {
        state = STATE_DONE;
    }
}

void configXmlPage::slot_http_sslErrors(const QList<QSslError> &errors)
{
    qDebug() << "configXmlPage::http::slot_http_sslErrors";
    Q_UNUSED(errors);
    http.ignoreSslErrors();
}

void configXmlPage::slot_http_readyRead(const QHttpResponseHeader & resp)
{
    Q_UNUSED(resp);
    response.append(http.readAll());
}
